/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package redis.clients.jedis.resps;

import java.io.Serializable;
import java.util.*;

/**
 * This class holds information about an Access Control Log entry (returned by ACL LOG command) They
 * can be access via getters. For future purpose there is also {@link #getlogEntry} method that
 * returns a generic {@code Map} - in case where more info is returned from a server
 */
public class AccessControlLogEntry implements Serializable {

    private static final long serialVersionUID = 1L;

    public static final String COUNT = "count";
    public static final String REASON = "reason";
    public static final String CONTEXT = "context";
    public static final String OBJECT = "object";
    public static final String USERNAME = "username";
    public static final String AGE_SECONDS = "age-seconds";
    public static final String CLIENT_INFO = "client-info";
    // Redis 7.2
    public static final String ENTRY_ID = "entry-id";
    public static final String TIMESTAMP_CREATED = "timestamp-created";
    public static final String TIMESTAMP_LAST_UPDATED = "timestamp-last-updated";

    private final long count;
    private final String reason;
    private final String context;
    private final String object;
    private final String username;
    private final String ageSeconds;
    private final Map<String, String> clientInfo;
    private final Map<String, Object> logEntry;
    private final long entryId;
    private final long timestampCreated;
    private final long timestampLastUpdated;

    public AccessControlLogEntry(Map<String, Object> map) {
        count = (long) map.get(COUNT);
        reason = (String) map.get(REASON);
        context = (String) map.get(CONTEXT);
        object = (String) map.get(OBJECT);
        username = (String) map.get(USERNAME);
        ageSeconds = (String) map.get(AGE_SECONDS);
        clientInfo = getMapFromRawClientInfo((String) map.get(CLIENT_INFO));
        logEntry = map;
        entryId = (long) map.get(ENTRY_ID);
        timestampCreated = (long) map.get(TIMESTAMP_CREATED);
        timestampLastUpdated = (long) map.get(TIMESTAMP_LAST_UPDATED);
    }

    public long getCount() {
        return count;
    }

    public String getReason() {
        return reason;
    }

    public String getContext() {
        return context;
    }

    public String getObject() {
        return object;
    }

    public String getUsername() {
        return username;
    }

    public String getAgeSeconds() {
        return ageSeconds;
    }

    public Map<String, String> getClientInfo() {
        return clientInfo;
    }

    /**
     * @return Generic map containing all key-value pairs returned by the server
     */
    public Map<String, Object> getlogEntry() {
        return logEntry;
    }

    public long getEntryId() {
        return entryId;
    }

    public long getTimestampCreated() {
        return timestampCreated;
    }

    public long getTimestampLastUpdated() {
        return timestampLastUpdated;
    }

    /**
     * Convert the client-info string into a Map of String. When the value is empty, the value in the
     * map is set to an empty string The key order is maintained to reflect the string return by Redis
     *
     * @param clientInfo
     * @return A Map with all client info
     */
    private Map<String, String> getMapFromRawClientInfo(String clientInfo) {
        String[] entries = clientInfo.split(" ");
        Map<String, String> clientInfoMap = new LinkedHashMap<>(entries.length);
        for (String entry : entries) {
            String[] kvArray = entry.split("=");
            clientInfoMap.put(kvArray[0], (kvArray.length == 2) ? kvArray[1] : "");
        }
        return clientInfoMap;
    }

    @Override
    public String toString() {
        return "AccessControlLogEntry{"
                + "count="
                + count
                + ", reason='"
                + reason
                + '\''
                + ", context='"
                + context
                + '\''
                + ", object='"
                + object
                + '\''
                + ", username='"
                + username
                + '\''
                + ", ageSeconds='"
                + ageSeconds
                + '\''
                + ", clientInfo="
                + clientInfo
                + ", entryId="
                + entryId
                + ", timestampCreated="
                + timestampCreated
                + ", timestampLastUpdated="
                + timestampLastUpdated
                + '}';
    }
}
